// 引入Cesium库
import * as Cesium from 'cesium';
/**
 * @description cesium绘制 点、线、面
 * @export
 * @class Draw
 * @example
 */
function Draw(viewer, config) {
    this.viewer = viewer;
    // 默认配置
    this.config = config || {
        // 几何-边框宽度
        borderWidth: 2,
        // 几何-边框颜色
        borderColor: Cesium.Color.WHITE,
        lineColor: Cesium.Color.fromCssColorString('#00ffff'),
        // 填充材质
        material: Cesium.Color.fromCssColorString('#00ffff').withAlpha(0.4)
    };

    this.polygon_point_arr = []; // 多边形全部点的数组
    this.polyline_point_arr = []; // 折线全部点的数组
    this.temporary_polygon_entity = null; // 临时多边形entity
    this.temporary_polyline_entity = null; // 临时线
    this.temporary_point_entity = null; // 临时点
    this.handler = null;
    this.type = 'polygon';
    this.onDrawEndCallbacks; // 用于存储绘制结束后的回调函数
}

/*******
 * @function: function
 * @return {*}
 * @description: 开启绘制的方法
 */
Draw.prototype.clickDrawPolygon = function (type = 'polygon', onDrawEnd) {
    this.type = type;

    if (onDrawEnd) {
        this.onDrawEndCallbacks = onDrawEnd;
    }

    // 清空多边形点数组，用于下次绘制
    this.polygon_point_arr = [];

    // 清空多边形点数组，用于下次绘制
    this.polyline_point_arr = [];

    console.log('click_draw_polygon');
    // 清除可能会用到的监听事件
    if (this.handler) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    }
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

    //鼠标左键--确定选中点
    this.handler.setInputAction((event) => {
        // 屏幕坐标转为空间坐标
        let cartesian = this.viewer.camera.pickEllipsoid(event.position, this.viewer.scene.globe.ellipsoid);

        // 判断是否定义（是否可以获取到空间坐标）
        if (Cesium.defined(cartesian)) {
            let ellipsoid = this.viewer.scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(cartesian);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度

            //如果类型是点，则左键直接结束
            if (this.type === 'point') {
                this.polyline_point_arr = [lon, lat];
                this.draw_end();
                return;
            }
            // 判断是否开始绘制折线
            if (this.temporary_polyline_entity == null) {
                // 注意顺序不能错了，先经度后纬度，这里是初次点击时初始化两个经纬度点添加折线
                this.polyline_point_arr.push(lon);
                this.polyline_point_arr.push(lat);
                this.polyline_point_arr.push(lon);
                this.polyline_point_arr.push(lat);

                // 绘制动态折线
                this.draw_dynamic_polyline();
            } else {
                // 添加折线
                this.polyline_point_arr.push(lon);
                this.polyline_point_arr.push(lat);
            }

            if (this.type === 'polygon') {
                // 将点添加进保存多边形点的数组中，鼠标停止移动的时添加的点和，点击时候添加的点，坐标一样
                this.polygon_point_arr.push(cartesian);
                // 判断是否开始绘制动态多边形，没有的话则开始绘制
                if (this.temporary_polygon_entity == null) {
                    // 绘制动态多边形
                    this.draw_dynamic_polygon();
                }
            }
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    //鼠标移动--实时绘制
    this.handler.setInputAction((event) => {
        // 屏幕坐标转为空间坐标
        let cartesian = this.viewer.camera.pickEllipsoid(event.endPosition, this.viewer.scene.globe.ellipsoid);
        // 判断是否定义（是否可以获取到空间坐标）
        if (Cesium.defined(cartesian)) {
            // 判断是否已经开始绘制动态多边形，已经开始的话，则可以动态拾取鼠标移动的点，修改点的坐标
            if (this.temporary_polygon_entity) {
                // 只要元素点大于一，每次就删除一个点，因为实时动态的点是添加上去的
                if (this.polygon_point_arr.length > 1) {
                    // 删除数组最后一个元素（鼠标移动添加进去的点）
                    this.polygon_point_arr.pop();
                }
                // 将新的点添加进动态多边形点的数组中，用于实时变化，注意：这里是先添加了一个点，然后再删除点，再添加，这样重复的
                this.polygon_point_arr.push(cartesian);
            }

            let ellipsoid = this.viewer.scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(cartesian);
            let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
            let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
            // 判断是否已经开始绘制动态线，已经开始的话，则可以动态拾取鼠标移动的点，修改点的坐标
            if (this.temporary_polyline_entity) {
                // 只要元素点大于二，每次就删除二个点，因为实时动态的点是添加上去的
                if (this.polyline_point_arr.length > 2) {
                    // 删除数组最后两个元素（鼠标移动添加进去的点）
                    this.polyline_point_arr.pop();
                    this.polyline_point_arr.pop();
                }
                // 将新的点添加进动态线的坐标的数组中，用于实时变化，注意：这里是先添加了一个点，然后再删除点，再添加，这样重复的
                // 注意顺序不能错了，先经度后纬度
                this.polyline_point_arr.push(lon);
                this.polyline_point_arr.push(lat);
            }

            //添加跟随鼠标移动的点
            if (this.temporary_point_entity) {
                this.temporary_point_entity.position = cartesian;
            } else {
                this.temporary_point_entity = this.viewer.entities.add({
                    position: Cesium.Cartesian3.fromDegrees(1, 1), // 设置点的经纬度位置
                    point: {
                        pixelSize: 10, // 点的大小
                        color: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)'), // 点的颜色
                        outlineColor: Cesium.Color.WHITE, // 点的边框颜色（可选）
                        outlineWidth: 2 // 点的边框宽度（可选）
                    }
                });
            }
        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    //鼠标右键--结束绘制
    this.handler.setInputAction((event) => {
        // 取消鼠标移动监听
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        if (this.type === 'polygon') {
            // 清除动态绘制的多边形
            this.viewer.entities.remove(this.temporary_polygon_entity);
            // 删除保存的临时多边形的entity
            this.temporary_polygon_entity = null;
        }

        // 清除动态绘制的折线
        this.viewer.entities.remove(this.temporary_polyline_entity);
        // 删除保存的临时折线的entity
        this.temporary_polyline_entity = null;

        // 清除动态绘制的点
        this.viewer.entities.remove(this.temporary_point_entity);
        // 删除保存的临时点的entity
        this.temporary_point_entity = null;

        // 绘制结果多边形
        this.draw_polygon();

        // 清除所有事件
        if (this.handler) {
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
};

Draw.prototype.draw_end = function () {
    // 取消鼠标移动监听
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // 清除动态绘制的点
    this.viewer.entities.remove(this.temporary_point_entity);
    // 删除保存的临时点的entity
    this.temporary_point_entity = null;

    // 绘制结果多边形
    this.draw_polygon();

    // 清除所有事件
    if (this.handler) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    }
};

//绘制动态多边形
Draw.prototype.draw_dynamic_polygon = function () {
    this.temporary_polygon_entity = this.viewer.entities.add({
        polygon: {
            // 这个方法上面有重点说明
            hierarchy: new Cesium.CallbackProperty(() => {
                // PolygonHierarchy 定义多边形及其孔的线性环的层次结构（空间坐标数组）
                return new Cesium.PolygonHierarchy(this.polygon_point_arr);
            }, false),
            extrudedHeight: 0, // 多边体的高度（多边形拉伸高度）
            height: 0, // 多边形离地高度
            material: Cesium.Color.fromCssColorString('rgba(196, 196, 196, 0.5)')
        }
    });
};

//绘制动态折线
Draw.prototype.draw_dynamic_polyline = function () {
    this.temporary_polyline_entity = this.viewer.entities.add({
        polyline: {
            positions: new Cesium.CallbackProperty(() => {
                // 返回线的顶点数组
                return new Cesium.Cartesian3.fromDegreesArray(this.polyline_point_arr); // 线的顶点
            }, false),
            width: 3, // 线的宽度
            material: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)'), // 线的颜色和透明度
            show: true
        }
    });
};

//绘制结果多边形
Draw.prototype.draw_polygon = function () {
    // 删除最后一个动态添加的点，如果鼠标没移动，最后一个和倒数第二个是一样的，所以也要删除
    this.polygon_point_arr.pop();

    if (this.polyline_point_arr.length > 4) {
        this.polyline_point_arr.splice(this.polyline_point_arr.length - 4, 4);
    }

    if (this.type === 'polygon') {
        if (this.polygon_point_arr.length >= 3) {
            // 三个点以上才能绘制成多边形
            let polygon_entity = this.viewer.entities.add({
                polygon: {
                    hierarchy: this.polygon_point_arr,
                    extrudedHeight: 0, // 多边体的高度（多边形拉伸高度）
                    height: 10, // 多边形离地高度
                    material: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)'),
                    outline: true, // 显示边线
                    outlineColor: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)'),
                    outlineWidth: 2
                }
            });
        }
    } else if (this.type === 'polyline') {
        if (this.polyline_point_arr.length >= 4) {
            const polyline_entity = this.viewer.entities.add({
                polyline: {
                    positions: Cesium.Cartesian3.fromDegreesArray(this.polyline_point_arr),
                    width: 3,
                    material: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)')
                }
            });
        }
    } else if (this.type === 'point') {
        const point_entity = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(this.polyline_point_arr[0], this.polyline_point_arr[1]),
            point: {
                pixelSize: 10,
                color: Cesium.Color.fromCssColorString('rgba(0, 153, 255, 1)')
            }
        });
    }

    // 坐标转换--这里可以输出所有点位坐标，不需要就删除了
    // let point_arr = [];
    // this.polygon_point_arr.forEach(val => {
    //   let polyObj = {}
    //   let cartographic = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(val)
    //   polyObj.lon = Cesium.Math.toDegrees(cartographic.longitude)
    //   polyObj.lat = Cesium.Math.toDegrees(cartographic.latitude)
    //   point_arr.push([polyObj.lon, polyObj.lat])
    // })

    // 调用绘制结束后的回调函数
    this.onDrawEndCallbacks(this.polyline_point_arr);
};
export default Draw;
